#pragma once
#include <string>
#include <map>
#include <set>

namespace timer
{
	struct ProfilerInfo
	{
		std::string FunctionSignature;
		std::string FileName;
		int LineNumber;
		double AvgInvocationTime;
		double AvgFrequentInvocationTime;
		__int64 InvocationTimes;
		__int64 LastTimeSignature;
	};

	struct ProfilerInfoSorter
	{
		/*! Profiler Information Sorter
		 *  This sorting algorithm is used to sort the information to the most priority item to the least.
		 */
		bool operator()(ProfilerInfo const *_Lhs, ProfilerInfo const *_Rhs) const
		{
			double lhs_val = _Lhs->AvgInvocationTime * _Lhs->InvocationTimes * 1.0/(1.0 + _Lhs->AvgFrequentInvocationTime);
			double rhs_val = _Rhs->AvgInvocationTime * _Rhs->InvocationTimes * 1.0/(1.0 + _Rhs->AvgFrequentInvocationTime);
			if(lhs_val > rhs_val) return true;
			return false;
		}
	};

	class RefCountTimer;

	class ProfilerManager
	{
		friend class RefCountTimer;

	public:
		typedef std::map<std::string, ProfilerInfo *> ProfilerMap;
		typedef ProfilerMap::iterator ProfilerMapIterator;
		typedef ProfilerMap::const_iterator ProfilerMapConstIterator;
		typedef std::set<ProfilerInfo const *, ProfilerInfoSorter> SortedProfilerSet;
		typedef SortedProfilerSet::iterator SortedProfilerSetIterator;
		typedef SortedProfilerSet::const_iterator SortedProfilerSetConstIterator;

		/*! Singleton instance getter.
		 *  returns the reference to the singleton object
		 */
		static ProfilerManager & getInstance();

		/*! Reseter
		 *  Resets the manager
		 */
		void Clear();

		/*! Retrieves the information set ordered by priority
		 */
		void getPrioritySet(SortedProfilerSet &_SortedSet) const;

		/*! Prints the priority set in the debug output
		 */
		void DebugPrintInfo() const;

	private:
		/*! Constructor.
		 */
		ProfilerManager(void);

		/*! Destructor.
		 *  Prints the priority set when destructs
		 */
		~ProfilerManager(void);

		ProfilerMap m_profiler_map;

	};
}